#include "powermanage.h"
#include <stdio.h>
#include "drv_pin.h"
#include "drv_rtc.h"
#include "main.h"
#include "delay.h"
#include "drv_timer.h"
#include "drv_adc.h"
#include "drv_can.h"
#include "drv_usart1.h"
#include "24Cxx.h"
#include "BQ769xx.h"
#include "tm1650.h"
#include "systemdata.h"
#include "wakeup.h"
#include "bat_afe.h"
#include <stdlib.h>
#include "lightboard.h"
#include "ocv_table.h"
#include "timer0.h"
#include "debug_uart.h"
#include "dvc.h"

static Timer_t *power_manage_timer = NULL;
static SysConfData_t *confinfo = NULL;
static SysRunData_t  *runinfo  = NULL;
static uint64_t sysRunningStartTime = 0;

static void peripheral_sleep_enter(void){
	drv_adc_sleep_enter();
	usart4_sleep_enter();
	usart2_sleep_enter();
//	afe_sleep_enter();
	afe_poweroff();
}

//关电源
static void power_sleep_enter(void){
	hc32_pin_mode(LED_STA_PIN,PIN_MODE_OUTPUT);
	hc32_pin_mode(RS485_PWC_PIN,PIN_MODE_OUTPUT);
	hc32_pin_mode(MCU_LINK_PIN,PIN_MODE_OUTPUT);
	hc32_pin_mode(MCU_POWER_DVC,PIN_MODE_OUTPUT);
	

	hc32_pin_write(LED_STA_PIN,PIN_HIGH);
	hc32_pin_write(RS485_PWC_PIN,PIN_LOW);
	hc32_pin_write(MCU_LINK_PIN,PIN_LOW);
	hc32_pin_write(MCU_POWER_DVC,PIN_LOW);
	

	hc32_pin_mode(USART2_RX,PIN_MODE_OUTPUT);
	hc32_pin_mode(USART2_TX,PIN_MODE_OUTPUT);
	hc32_pin_mode(USART4_RX,PIN_MODE_OUTPUT);
	hc32_pin_mode(USART4_TX,PIN_MODE_OUTPUT);
	hc32_pin_mode(RS_485_EN_PIN,PIN_MODE_OUTPUT);


	hc32_pin_write(USART2_RX,PIN_LOW);
	hc32_pin_write(USART2_TX,PIN_LOW);
	hc32_pin_write(USART4_TX,PIN_LOW);
	hc32_pin_write(USART4_RX,PIN_LOW);
	hc32_pin_write(RS_485_EN_PIN,PIN_LOW);
	Delay_ms(100);
	hc32_pin_mode(IIC_SCL_PIN,PIN_MODE_OUTPUT);
	hc32_pin_mode(IIC_SDA_PIN,PIN_MODE_OUTPUT);
	hc32_pin_mode(AT_SDA_PIN,PIN_MODE_OUTPUT);
	hc32_pin_mode(AT_SCL_PIN,PIN_MODE_OUTPUT);
	hc32_pin_mode(MCU_NET_SLEEP,PIN_MODE_OUTPUT);

	hc32_pin_write(IIC_SCL_PIN,PIN_LOW);
	hc32_pin_write(IIC_SDA_PIN,PIN_LOW);
	hc32_pin_write(AT_SDA_PIN,PIN_LOW);
	hc32_pin_write(AT_SCL_PIN,PIN_LOW);
	hc32_pin_write(MCU_NET_SLEEP,PIN_HIGH);
	Delay_ms(100);
}

static void rs485_power_manage(void *data){
	static uint16_t timeout_cnt_ms = 0;
	static uint16_t obc_link_timeout_cnt_ms = 0;
	if (runinfo->comLinkState.Bits.rs485_lpwr_flag == 0){
		if (runinfo->comLinkState.Bits.rs485_link == 1){ // 如果收到485通讯标志为真
			runinfo->comLinkState.Bits.rs485_link = 0;
			timeout_cnt_ms = 0;
		}else{
			timeout_cnt_ms += *(uint32_t *)data;
		}
		if (runinfo->wakeState.bits.RS485_WAKE == 1){
			runinfo->wakeState.bits.RS485_WAKE = 0;
			wake_flag_clear(rs485_wake_bit);
		}
		if(runinfo->comLinkState.Bits.rs485_obc_timeout == 1){//检测到充电机485通讯超时
			obc_link_timeout_cnt_ms += *(uint32_t *)data;
		}else{
			runinfo->comLinkState.Bits.rs485_obc_timeout = 1;//重新置1
			obc_link_timeout_cnt_ms = 0;
		}
		if (obc_link_timeout_cnt_ms >= 2000){ // 充电机通讯超时5秒
			obc_link_timeout_cnt_ms = 0;
			runinfo->comLinkState.Bits.rs485_obc_link = 0;//充电机连接标志置0
			runinfo->comLinkState.Bits.chgCbtOutTimeState = 1;
		}
		if (timeout_cnt_ms >= 5000){ // 通讯超时5秒
			printf("rs485 lowpower mode enter\n");
			runinfo->comLinkState.Bits.rs485_obc_link = 0; // 充电机连接状态清除
			timeout_cnt_ms = 0;
			runinfo->comLinkState.Bits.rs485_lpwr_flag = 1;
			usart4_sleep_enter();
			hc32_pin_write(RS485_PWC_PIN, PIN_LOW);
			wake_enable(rs485_wake_bit, Enable);

		}
	}else{
		timeout_cnt_ms = 0;
		if (runinfo->wakeState.bits.RS485_WAKE == 1){
			printf("rs485 lowpower mode exit\n");
			wake_flag_clear(rs485_wake_bit);
			wake_enable(rs485_wake_bit, Disable);
			hc32_pin_write(RS485_PWC_PIN, PIN_HIGH);
			if (runinfo->low_pwr_flag == 0){
				usart4_init(getSysConfData()->zhixiangParam.serialPortBaudRate.value * 100);
			}
			runinfo->comLinkState.Bits.rs485_lpwr_flag = 0;
		}
	}
}

static void can_power_manage(void  *data){
	static uint16_t timeout_cnt_ms = 0;
	static uint16_t obc_link_timeout_cnt_ms = 0;
	if (runinfo->comLinkState.Bits.can_lpwr_flag == 0){
		if (runinfo->comLinkState.Bits.can_link == 1){ // 如果收到can通讯标志为真
			runinfo->comLinkState.Bits.can_link = 0;
			timeout_cnt_ms = 0;
		}else{
			timeout_cnt_ms += *(uint32_t *)data;
		}
		if (runinfo->wakeState.bits.CAN_WAKE == 1){
			runinfo->wakeState.bits.CAN_WAKE = 0;
			wake_flag_clear(can_wake_bit);
		}
		if(runinfo->comLinkState.Bits.can_obc_timeout == 1){//检测到充电机can通讯超时
			obc_link_timeout_cnt_ms += *(uint32_t *)data;
		}else{
			runinfo->comLinkState.Bits.can_obc_timeout = 1;//重新置1
			obc_link_timeout_cnt_ms = 0;
		}
		if (obc_link_timeout_cnt_ms >= 5000){ // 充电机通讯超时5秒
			obc_link_timeout_cnt_ms = 0;
			runinfo->comLinkState.Bits.can_obc_link = 0;//充电机连接标志置0
		}
		if (timeout_cnt_ms >= 5000){ // 通讯超时5秒
			timeout_cnt_ms = 0;
			printf("can lowpower mode enter\n");
			runinfo->comLinkState.Bits.can_obc_link = 0; // 充电机连接状态清除
			runinfo->comLinkState.Bits.can_lpwr_flag = 1;
			drv_can_sleep_enter();
			hc32_pin_write(CAN_PWC_PIN, PIN_LOW);
			Delay_ms(50);
			wake_enable(can_wake_bit, Enable);
		}
	}else{
		timeout_cnt_ms = 0;
		if (runinfo->wakeState.bits.CAN_WAKE == 1){
			printf("can lowpower mode exit\n");
			wake_flag_clear(can_wake_bit);
			wake_enable(can_wake_bit, Disable);
			hc32_pin_write(CAN_PWC_PIN, PIN_HIGH);
			drv_can_sleep_exit();
			runinfo->comLinkState.Bits.can_lpwr_flag = 0;
		}
	}
}

void system_poweroff(void){
	printf(" enter poweroff mode\n");
	peripheral_sleep_enter();
	power_sleep_enter();
	PWC_ClearWakeup0Flag(PWC_PTWK0_WKUPFLAG);
	PWC_ClearWakeup0Flag(PWC_PTWK1_WKUPFLAG);
	PWC_ClearWakeup1Flag(PWC_WKTM_WKUPFLAG);
	RMU_ClrResetFlag();
	PWC_EnterPowerDownMd();
}


static void sys_lpwr_process(void *data){
	static uint32_t sys_lpwr_enter_time_cnt = 0; // 进入低功耗计时
	static uint32_t sys_lpwr_exit_time_cnt = 0; // 进入低功耗计时
//	printf("rs485_lpwr_flag  = %d\n",runinfo->comLinkState.Bits.rs485_lpwr_flag);
	if ((runinfo->batState != chgState) && (runinfo->batState != dsgState) && (runinfo->comLinkState.Bits.rs485_lpwr_flag == 1)){ // 不是充电状态或放电状态,没有通信
		if (runinfo->low_pwr_flag == 0){
			sys_lpwr_enter_time_cnt += *(uint32_t *)data;
			if (sys_lpwr_enter_time_cnt >= 60 * 1000){ // 	不充电不放电情况下，60秒进入低功耗状态
				runinfo->low_pwr_flag = 1;
				sys_lpwr_enter_time_cnt = 0;
				printf("system enter low power mode\n");
				afe_set_cellvol_period(CC2_8Period);
				Delay_ms(5);
				HC32F460_SYSCLK_Low_Power_Init();
				Timer0_Low_Power_Init();
				USART3_Init(115200);
				usart2_init(9600);
			}
		}
	}else{
		if (runinfo->low_pwr_flag == 1){
			printf("system exit low power mode\n");
			Delay_ms(5);		
			HC32F460_SYSCLK_Init();
			Timer0_Init();
			USART3_Init(115200);
			usart2_init(9600);
			if(runinfo->comLinkState.Bits.rs485_lpwr_flag == 0){//如果此时485没有在低功耗状态
				usart4_init(9600);
			}
			
			afe_set_cellvol_period(CC2_1Period);
			runinfo->low_pwr_flag = 0;
		}
		sys_lpwr_enter_time_cnt = 0;
		sys_lpwr_exit_time_cnt = 0;
	}
}

static void stateled_ctrl_process(){
	static uint64_t led_sta = 0;
	if (runinfo->low_pwr_flag == 0){
		hc32_pin_write(LED_STA_PIN, (led_sta++) % 20);
	}else{
		hc32_pin_write(LED_STA_PIN, (led_sta++) % 1200);
	}
}

static void system_runTime_update_process(void *data){
	static uint32_t sysRunTimeCnt = 0;
	sysRunTimeCnt += *(uint32_t *)data;
	if(sysRunTimeCnt >= 60000){
		sysRunTimeCnt -= 60000;
		runinfo->sysRunTime_min++;
	}
}

static void power_manage_timer_callback(void *data){
	//printf("Delta Time = %dmS\n",*(uint32_t *)data);
	stateled_ctrl_process();
	rs485_power_manage(data);
	sys_lpwr_process(data);
	system_runTime_update_process(data);
}

void powerManageInit(void){
	runinfo = getSysRunData();
	confinfo = getSysConfData();
	hc32_pin_mode(RS485_PWC_PIN,PIN_MODE_OUTPUT);
	hc32_pin_mode(MCU_LINK_PIN,PIN_MODE_OUTPUT);
	hc32_pin_mode(LED_STA_PIN,PIN_MODE_OUTPUT);
	hc32_pin_mode(MCU_NET_SLEEP,PIN_MODE_OUTPUT);
	hc32_pin_mode(LOAD_DET_PIN,PIN_MODE_INPUT);
	
	hc32_pin_write(LED_STA_PIN,PIN_LOW);
	hc32_pin_write(RS485_PWC_PIN,PIN_HIGH);
	hc32_pin_write(MCU_LINK_PIN,PIN_HIGH);
	hc32_pin_write(MCU_NET_SLEEP,PIN_HIGH);
	
	power_manage_timer = timer_create(power_manage_timer_callback,100);
	timer_start(power_manage_timer);
	runinfo->low_pwr_flag = 0;
	runinfo->sysRunTime_min = 0;
//	runinfo->sysStartTime_min = getTimeStamp()/60;
	
}